package com.kellycheung.chicken_go_go;

public class GPosition {
	protected enum GPXDirection {
		left(-1), right(1), none(0);
		
		private final int iXDir;
		
		private GPXDirection( final int p_iXDir ) { 
			this.iXDir = p_iXDir;
		}
		
		public static GPXDirection getXDirection( float p_fXSpeed ) {
			GPXDirection xd;
			
			if ( p_fXSpeed > 0 ) {
				xd = GPXDirection.right;
			} else if ( p_fXSpeed < 0 ) {
				xd = GPXDirection.left;
			} else {
				xd = GPXDirection.none;
			}
			
			return xd;
		}	}
	
	protected enum GPYDirection {
		up(-1), down(1), none(0);
		
		private final int iYDir;
		
		private GPYDirection( final int p_iYDir ) { 
			this.iYDir = p_iYDir;
		}
		
		public static GPYDirection getYDirection( float p_fYSpeed ) {
			GPYDirection yd;
			
			if ( p_fYSpeed > 0 ) {
				yd = GPYDirection.down;
			} else if ( p_fYSpeed < 0 ) {
				yd = GPYDirection.up;
			} else {
				yd = GPYDirection.none;
			}
			
			return yd;
		}
		
	}
	
	protected GCoordinate gcThis;
	protected GRectangle grLimit;
	
	protected float fXSpeed;
	protected float fXSpeedMax;
	protected float fYSpeed;
	protected float fYSpeedMax;
	protected float fXAcc;
	protected float fYAcc;
	protected GPXDirection gpxdDir;
	protected GPYDirection gpydDir;
	protected boolean bStopWhenXDirChg;
	protected boolean bStopWhenYDirChg;
	
	public GPosition( float p_fX , float p_fY ) {
		this( new GCoordinate( p_fX , p_fY ) );
	}
		
	public GPosition( GCoordinate p_gc ) {
		try {
			this.gcThis = new GCoordinate( p_gc.fX , p_gc.fY );
			
			this.setXSpeed( 0f );
			this.setYSpeed( 0f );
			this.setXSpeedMax( 0f );
			this.setYSpeedMax( 0f );
			this.setXAcc( 0f , false );
			this.setYAcc( 0f , false );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition(GCoordinate)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public GPosition( GPosition p_gp ) {
		try {
			this.gcThis = new GCoordinate( p_gp.gcThis );
			
			this.setXSpeed( p_gp.fXSpeed );
			this.setYSpeed( p_gp.fYSpeed );
			this.setXSpeedMax( p_gp.fXSpeedMax );
			this.setYSpeedMax( p_gp.fYSpeedMax );
			this.setXAcc( p_gp.fXAcc , p_gp.bStopWhenXDirChg );
			this.setYAcc( p_gp.fYAcc , p_gp.bStopWhenYDirChg );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition(GPosition)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void destroy() {
		try {
			this.gcThis = null;
			this.grLimit = null;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.destroy" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setXSpeed( float p_fXSpeed ) {
		try {
			this.fXSpeed = p_fXSpeed;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setXSpeed" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setYSpeed( float p_fYSpeed ) {
		try {
			this.fYSpeed = p_fYSpeed;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setYSpeed" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setXSpeedMax( float p_fXSpeedMax ) {
		try {
			this.fXSpeedMax = Math.abs(p_fXSpeedMax);
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setXSpeedMax" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setYSpeedMax( float p_fYSpeedMax ) {
		try {
			this.fYSpeedMax = Math.abs(p_fYSpeedMax);
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setYSpeedMax" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setXAcc( float p_fXAcc , boolean p_bStopWhenXDirChg ) {
		try {
			this.fXAcc = p_fXAcc;
			
			this.bStopWhenXDirChg = p_bStopWhenXDirChg;
			this.gpxdDir = GPXDirection.getXDirection( this.fXSpeed );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setXAcc" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setYAcc( float p_fYAcc , boolean p_bStopWhenYDirChg ) {
		try {
			this.fYAcc = p_fYAcc;
			
			this.bStopWhenYDirChg = p_bStopWhenYDirChg;
			this.gpydDir = GPYDirection.getYDirection( this.fYSpeed );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setYAcc" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setLimit( float p_fRight , float p_fUp , float p_fLeft , float p_fDown ) {
		try {
			this.setLimit( new GRectangle( p_fRight , p_fUp , p_fLeft , p_fDown ) );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setLimit(float,float,float,float)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setLimit( GRectangle p_gr ) {
		try {
			this.grLimit = new GRectangle( p_gr );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.setLimit(GRectangle)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void toNewPoint() {
		try {
			this.fXSpeed = this.fXSpeed + this.fXAcc;
			this.fYSpeed = this.fYSpeed + this.fYAcc;
			
			if ( Math.abs(this.fXSpeed) > Math.abs(this.fXSpeedMax) && this.fXSpeedMax != 0f ) {
				this.fXSpeed = Math.abs(this.fXSpeedMax) * ( this.fXSpeed / Math.abs(this.fXSpeed) );
			}
			
			if ( Math.abs(this.fYSpeed) > Math.abs(this.fYSpeedMax) && this.fYSpeedMax != 0f ) {
				this.fYSpeed = Math.abs(this.fYSpeedMax) * ( this.fYSpeed / Math.abs(this.fYSpeed) );
			}
			
			if ( this.bStopWhenXDirChg ) {
				if ( this.gpxdDir == GPXDirection.none ) {
					this.gpxdDir = GPXDirection.getXDirection(this.fXSpeed);
				}

				if ( this.gpxdDir != GPXDirection.getXDirection(this.fXSpeed) ) {
					this.fXSpeed = 0f;
					this.fXAcc = 0f;
					this.gpxdDir = GPXDirection.none;
				}
			}
			
			if ( this.bStopWhenYDirChg ) {
				if ( this.gpydDir == GPYDirection.none ) {
					this.gpydDir = GPYDirection.getYDirection(this.fYSpeed);
				}

				if ( this.gpydDir != GPYDirection.getYDirection(this.fYSpeed) ) {
					this.fYSpeed = 0f;
					this.fYAcc = 0f;
					this.gpydDir = GPYDirection.none;
				}
			}
			
			this.gcThis.set( this.gcThis.fX + this.fXSpeed , this.gcThis.fY + this.fYSpeed , this.grLimit );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GPosition.toNewPoint" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public String toString() {
		return "XY:" + this.gcThis.toString( false );
	}
	
	public String toString( boolean p_bRound ) {
		return "XY:" + this.gcThis.toString( p_bRound )
			+ "; XYDir:" + String.valueOf(Math.floor(this.gpxdDir.iXDir*10.0)/10.0) + "," + String.valueOf(Math.floor(this.gpydDir.iYDir*10.0)/10.0)
			+ "; XYSpd:" + String.valueOf(Math.floor(this.fXSpeed*10.0)/10.0) + "," + String.valueOf(Math.floor(this.fYSpeed*10.0)/10.0) 
			+ "; XYSpdMax:" + String.valueOf(Math.floor(this.fXSpeedMax*10.0)/10.0) + "," + String.valueOf(Math.floor(this.fYSpeedMax*10.0)/10.0) 
			+ "; XYAcc:" + String.valueOf(Math.floor(this.fXAcc*10.0)/10.0) + "," + String.valueOf(Math.floor(this.fYAcc*10.0)/10.0) 
			;
	}
}
